iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 6
0
AI & Data

量化交易30天系列 第 6

量化交易30天 Day6 - 用RSI指標來做交易

  • 分享至 

  • xImage
  •  

量化交易30天
本系列文章是紀錄一位量化交易新手的學習過程,除了基礎的Python語法不說明,其他金融相關的東西都會一步步地說明,希望讓更多想學習量化交易但是沒有學過相關金融知識的朋友們,透過這系列的文章,能夠對量化交易略知一二,也歡迎量化交易的高手們多多交流。

上一篇的最後將RSI指標的計算寫成一個函數,本篇將介紹如何使用RSI做交易,並且以2019年的資料實際回測計算報酬率。

整理資料

# 串接API取資料
import os
import pandas_datareader as pdr
SPY = pdr.get_data_tiingo('SPY', api_key='YOUR API KEY')
SPY = SPY.reset_index(level=[0,1])
SPY.index = SPY['date']
SPY_adj = SPY.iloc[:,7:12]
SPY_adj.columns = ['Close','High','Low','Open','Volume']

# 篩選2019年收盤價資料
Close = SPY_adj.Close
Close2019 = Close['2019']

Close2019
------
date
2019-01-02 00:00:00+00:00    242.960053
2019-01-03 00:00:00+00:00    237.162341
2019-01-04 00:00:00+00:00    245.106275
2019-01-07 00:00:00+00:00    247.038845
2019-01-08 00:00:00+00:00    249.359872
                                ...    
2019-12-24 00:00:00+00:00    317.861656
2019-12-26 00:00:00+00:00    319.553725
2019-12-27 00:00:00+00:00    319.474564
2019-12-30 00:00:00+00:00    317.713229
2019-12-31 00:00:00+00:00    318.485050
Name: Close, Length: 252, dtype: float64

定義RSI函數

# RSI函數
def RSI(Close, period=12):
    # 整理資料
    import pandas as pd
    Chg = Close - Close.shift(1)
    Chg_pos = pd.Series(index=Chg.index, data=Chg[Chg>0])
    Chg_pos = Chg_pos.fillna(0)
    Chg_neg = pd.Series(index=Chg.index, data=-Chg[Chg<0])
    Chg_neg = Chg_neg.fillna(0)
    
    # 計算平均漲跌幅度
    import numpy as np
    up_mean = []
    down_mean = []
    for i in range(period+1, len(Chg_pos)+1):
        up_mean.append(np.mean(Chg_pos.values[i-period:i]))
        down_mean.append(np.mean(Chg_neg.values[i-period:i]))
    
    # 計算 RSI
    rsi = []
    for i in range(len(up_mean)):
        rsi.append( 100 * up_mean[i] / ( up_mean[i] + down_mean[i] ) )
    rsi_series = pd.Series(index = Close.index[period:], data = rsi)
    return rsi_series

觀察2019年的RSI資料

上一篇有提到用來計算RSI的天數,是根據個人需求而設定的,這邊我們先用14天來計算,因為這個天數還蠻多人使用的,之後會再說明天數最佳化的部分。

# 觀察2019年的RSI14
import matplotlib.pyplot as plt
RSI14_2019 = RSI(Close2019, 14)
plt.plot(RSI14_2019)
plt.title('2019年 RSI14')
plt.axhline(y=80, color='red')
plt.axhline(y=30, color='green')

來分析一下這張圖吧,可以看出2019年的RSI14大概會在20~100內波動,在這張圖內,我覺得超過80(紅色橫線的位置)就算是蠻高的,低於30(綠色橫線的位置)就算是偏低,我們用這兩個數字來試試看做交易,交易的策略是,在RSI14遇到綠色線的時候,代表相對股價較低,就將買入標的,一直到下一次遇到紅色線的時候,就將上次買入的部位全部賣掉,然後就重複這個步驟操作,直到最後一次賣出為止。

# 策略: RSI14 < 30 買進,RSI14 > 80 賣出

# 訊號標籤
sig = []

# 庫存標籤,只會是0或1,表示每次交易都是買進或賣出所有部位
stock = 0

# 偵測RSI14訊號
for i in range(len(RSI14_2019)):
    if RSI14_2019[i] > 80 and stock == 1:
        stock -= 1
        sig.append(-1)
    elif RSI14_2019[i] < 30 and stock == 0:
        stock += 1
        sig.append(1)
    else:
        sig.append(0)
# 將訊號整理成dataframe
rsi_sig = pd.Series(index = RSI14_2019.index, data = sig)

RSI訊號

import numpy as np
from matplotlib import gridspec
import pandas as pd

fig = plt.figure(figsize=(15,10))
# set height ratios for sublots
gs = gridspec.GridSpec(2, 1, height_ratios=[2, 1]) 

# the fisrt subplot
ax0 = plt.subplot(gs[0])
# line0 = ax0.plot(x, y, color='r')
ax0.plot(RSI14_2019)
ax0.axhline(y=80, color='red')
ax0.axhline(y=30, color='green')

#the second subplot
# shared axis X
ax1 = plt.subplot(gs[1], sharex = ax0)
rsi_sig = pd.Series(index = rsi_sig.index, data = list(rsi_sig.values))
ax1.plot(rsi_sig)

這張圖其實就是將上一張圖,加上下面藍色的訊號線的部分,可以看到這個訊號的確有照上面說的策略買賣,不過要記得,我們只能在訊號出現後的隔天交易,接下來就可以用這些買賣點,搭配開盤價的資料,計算報酬率。

計算報酬率

# 回測2019年 RSI14訊號 績效
# 取開盤價資料做回測,因為我們是在前一天收盤後看到訊號,隔天開盤才能買進
Open = SPY_adj.Open
Open2019 = Open['2019']

# 每次買賣的報酬率
rets = []
# 是否仍有庫存
stock = 0
# 當次交易買入價格
buy_price = 0
# 當次交易賣出價格
sell_price = 0
# 每次買賣的報酬率
for i in range(len(rsi_sig)):
    if rsi_sig[i] == 1:
        # 隔日開盤買入
        buy_price = Open2019[rsi_sig.index[i+1]]
        stock += 1
    elif rsi_sig[i] == -1:
        # 隔日開盤賣出
        sell_price = Open2019[rsi_sig.index[i+1]]
        stock -= 1
        rets.append((sell_price-buy_price)/buy_price)
        # 清除上次買賣的價格
        buy_price = 0
        sell_price = 0
# 總報酬率
total_ret = 1
for ret in rets:
    total_ret *= 1 + ret
print(str(round((total_ret - 1)*100,2)) + '%')
------
15.72%

最後算出來,2019年用RSI14去做交易的報酬率,回測大概是15.72%左右(不含手續費及稅費)。

本篇總結
這篇就先說明簡單的RSI交易策略,可以看到有幾個參數可以調整,包括:RSI的天數、回測的時間長度、判斷RSI過高與過低的標準...等等,下一篇就來實驗最佳化這些參數,看看能不能得到更好的報酬率吧。

P.S.
如果大家對於量化交易有興趣的話,我自己有上過以下這門課,課程內容從串接股市資料API、儲存至資料庫、將自己的策略轉化成程式碼、自動下單,並且可以把整個流程自動化,每天早上執行一次,一整天就不用看盤了,覺得是蠻實戰的,可以參考看看。

筆者 Sean
奈米戶投資人 / Python愛用者
喜歡用Python玩轉金融數據,從個股基本面、技術面、籌碼面相關資料,一直到總體經濟數據,都是平常接觸到的素材;對於投資,除了研究歷史數據,也喜歡瞭解市場上大家在玩些什麼。


上一篇
量化交易30天 Day5 - Python計算RSI
下一篇
量化交易30天 Day7 - RSI交易參數最佳化
系列文
量化交易30天30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言